home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 351-375 / 351 / pdc / pdcsrc.lzh / PDC / GenStmt.c < prev    next >
C/C++ Source or Header  |  1990-04-06  |  21KB  |  890 lines

  1.  
  2. /* PDC Compiler - A Freely Distributable C Compiler for the Amiga
  3.  *                Based upon prior work by Matthew Brandt and Jeff Lydiatt.
  4.  *
  5.  * PDC Compiler release 3.3 Copyright (C) 1989 Paul Petersen and Lionel Hummel.
  6.  * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
  7.  *
  8.  * This code is freely redistributable upon the conditions that this 
  9.  * notice remains intact and that modified versions of this file not be 
  10.  * distributed as part of the PDC Software Distribution without the express
  11.  * consent of the copyright holders.
  12.  *
  13.  *------------------------------------------------------------------
  14.  *
  15.  * $Log:    GenStmt.c,v $
  16.  * Revision 3.33  90/04/05  23:07:37  lionel
  17.  * Changed parameter convention to call_library to avoid name collisions.
  18.  * Added optional entry and exit routines that receive function name and stack usage as parameters.
  19.  * 
  20.  * Revision 3.32  90/02/03  16:24:20  lionel
  21.  * None
  22.  * 
  23.  *------------------------------------------------------------------
  24.  */
  25.  
  26. /*
  27.  * GenStmt.c Generates the assembly code.
  28.  */
  29.  
  30. #include    <stdio.h>
  31. #include    "C.h"
  32. #include    "Expr.h"
  33. #include    "Gen.h"
  34. #include    "Cglbdec.h"
  35. #include    <stab.h>
  36.  
  37. int             breaklab;
  38. int             contlab;
  39. int             retlab;
  40. int             fnamelab;
  41.  
  42. extern TYP      stdfunc;
  43. extern struct amode push[], pop[];
  44. extern struct enode *makenode();
  45. extern struct amode *make_label();
  46. extern struct amode *make_offset();
  47. extern struct amode *make_immed();
  48. extern struct amode *gen_expr();
  49. extern struct snode *makesnode();
  50. extern SYM     *gsearch();
  51. extern char    *itoa(), *litlate(), *in_line;
  52. extern char    *xalloc();
  53.  
  54. void   genstmt();
  55.  
  56. struct amode   *
  57. makedreg(r)
  58.  
  59. /*
  60.  * make an address reference to a data register.
  61.  */
  62.     enum e_am       r;
  63. {
  64.     struct amode   *ap;
  65.  
  66.     ap = (struct amode *) xalloc(sizeof(struct amode));
  67.     ap->mode = am_dreg;
  68.     ap->preg = r;
  69.     return ap;
  70. }
  71.  
  72. struct amode   *
  73. makeareg(r)
  74.  
  75. /*
  76.  * make an address reference to an address register.
  77.  */
  78.     enum e_am       r;
  79. {
  80.     struct amode   *ap;
  81.  
  82.     ap = (struct amode *) xalloc(sizeof(struct amode));
  83.     ap->mode = am_areg;
  84.     ap->preg = r;
  85.     return ap;
  86. }
  87.  
  88. struct amode   *
  89. make_mask(mask)
  90.  
  91. /*
  92.  * generate the mask address structure.
  93.  */
  94.     int             mask;
  95. {
  96.     struct amode   *ap;
  97.  
  98.     ap = (struct amode *) xalloc(sizeof(struct amode));
  99.     ap->mode = am_mask;
  100.     ap->offset = (struct enode *) mask;
  101.     return ap;
  102. }
  103.  
  104. struct amode   *
  105. make_direct(i)
  106.  
  107. /*
  108.  * make a direct reference to an immediate value.
  109.  */
  110.     char           *i;
  111. {
  112.     return make_offset(makenode(en_icon, i, NULL));
  113. }
  114.  
  115. struct amode   *
  116. make_intrlab(s)
  117.  
  118. /*
  119.  * generate a direct reference to an intrinsic label.
  120.  */
  121.     char           *s;
  122. {
  123.     struct amode   *ap;
  124.  
  125.     ap = (struct amode *) xalloc(sizeof(struct amode));
  126.     ap->mode = am_direct;
  127.     ap->offset = makenode(en_intrlab, s, NULL);
  128.     return ap;
  129. }
  130.  
  131. struct amode   *
  132. make_strlab(s)
  133.  
  134. /*
  135.  * generate a direct reference to a string label.
  136.  */
  137.     char           *s;
  138. {
  139.     struct amode   *ap;
  140.  
  141.     ap = (struct amode *) xalloc(sizeof(struct amode));
  142.     ap->mode = am_direct;
  143.     ap->offset = makenode(en_nacon, s, NULL);
  144.     return ap;
  145. }
  146.  
  147. int
  148. numlines(stmt)          /* Return 0, 1, 2, or 3 for number */
  149.  
  150. /*
  151.  *  Return the number of non-comment statements with a max of 3
  152.  */
  153.     struct snode   *stmt;
  154. {
  155.     int             count = 0;
  156.  
  157.     while (stmt != NULL) {
  158.         if (stmt->stype != st_comment) {
  159.             count++;
  160.             if (count > 2)
  161.                 return (count);
  162.         }
  163.         stmt = stmt->next;
  164.     }
  165.     return (count);
  166. }
  167.  
  168. void
  169. gencomment(stmt)
  170.  
  171. /*
  172.  * Generate a comment line
  173.  */
  174.     struct snode   *stmt;
  175. {
  176.     struct amode   *ap;
  177.  
  178.     ap = (struct amode *) xalloc(sizeof(struct amode));
  179.     ap->mode = am_direct;
  180.     ap->offset = stmt->exp;
  181.     gen_code(op_comment, 0, ap, NULL);
  182. }
  183.  
  184. void
  185. genasm(stmt)
  186.  
  187. /*
  188.  * Generate a assembly line
  189.  */
  190.     struct snode   *stmt;
  191. {
  192.     struct amode   *ap;
  193.  
  194.     ap = (struct amode *) xalloc(sizeof(struct amode));
  195.     ap->mode = am_direct;
  196.     ap->offset = stmt->exp;
  197.     gen_code(op_asm, 0, ap, NULL);
  198. }
  199.  
  200. void
  201. genstabn(stmt)
  202.  
  203. /*
  204.  * Generate a stabn statement
  205.  */
  206.     struct snode   *stmt;
  207. {
  208. #ifdef GENERATE_DBX
  209.     struct amode   *ap;
  210.     struct dnode   *dp;
  211.  
  212.     ap = (struct amode *) xalloc(sizeof(struct amode));
  213.     dp = stmt->exp->v.dp;
  214.     ap->mode = am_direct;
  215.     ap->offset = makenode(en_stabn, (struct enode *) dp, NULL);
  216.     gen_code(op_stabn, 0, ap, NULL);
  217. #endif
  218. }
  219.  
  220. void
  221. genstabs(stmt)
  222.  
  223. /*
  224.  * Generate a stabs statement
  225.  */
  226.     struct snode   *stmt;
  227. {
  228. #ifdef GENERATE_DBX
  229.     struct amode   *ap;
  230.     struct dnode   *dp;
  231.  
  232.     ap = (struct amode *) xalloc(sizeof(struct amode));
  233.     dp = stmt->exp->v.dp;
  234.     ap->mode = am_direct;
  235.     ap->offset = makenode(en_stabs, (struct enode *) dp, NULL);
  236.     gen_code(op_stabs, 0, ap, NULL);
  237. #endif
  238. }
  239.  
  240. void
  241. genwhile(stmt)
  242.  
  243. /*
  244.  * generate code to evaluate a while statement.
  245.  */
  246.     struct snode   *stmt;
  247. {
  248.     int             lab1, lab2;
  249.     int             determine, cond;
  250.  
  251.     initstack();        /* initialize temp registers */
  252.     lab1 = contlab;     /* save old continue label */
  253.     lab2 = breaklab;    /* save old break label */
  254.     contlab = nextlabel++;  /* new continue label */
  255.  
  256.  
  257.     determine = cond = FALSE;
  258.  
  259.     if (Options.Optimize) { /* Check for constant condition */
  260.         opt4(&stmt->exp);
  261.         if (stmt->exp != NULL && stmt->exp->nodetype == en_icon) {
  262.             determine = 1;
  263.             cond = (stmt->exp->v.i != 0);
  264.         }
  265.     }
  266.  
  267.     if (determine && !cond) /* Condition is always false */
  268.         return;
  269.  
  270.     gen_label(contlab);
  271.  
  272.     if (numlines(stmt->s1) > 0) {   /* has block */
  273.         breaklab = nextlabel++;
  274.         initstack();
  275.         if (!determine || !cond)
  276.             falsejp(stmt->exp, breaklab);
  277.         genstmt(stmt->s1);
  278.         gen_code(op_bra, 0, make_label(contlab), NULL);
  279.         gen_label(breaklab);
  280.         breaklab = lab2;/* restore old break label */
  281.     }
  282.     else {          /* no loop code */
  283.         initstack();
  284.         if (!determine || !cond)
  285.             truejp(stmt->exp, contlab);
  286.     }
  287.     contlab = lab1;     /* restore old continue label */
  288. }
  289.  
  290. void
  291. gen_for(stmt)
  292.  
  293. /*
  294.  * generate code to evaluate a for loop
  295.  */
  296.     struct snode   *stmt;
  297. {
  298.     int             old_break, old_cont, exit_label, loop_label, size;
  299.  
  300.     old_break = breaklab;
  301.     old_cont = contlab;
  302.     loop_label = nextlabel++;
  303.     exit_label = nextlabel++;
  304.     contlab = nextlabel++;
  305.     initstack();
  306.     if (stmt->label != NULL) {
  307.         size = natural_size(stmt->label);
  308.         gen_expr(stmt->label, F_ALL | F_NOVALUE | F_FREG, size );
  309.     }
  310.     gen_label(loop_label);
  311.     initstack();
  312.     if (stmt->exp != NULL)
  313.         falsejp(stmt->exp, exit_label);
  314.     if (numlines(stmt->s1) > 0) {
  315.         breaklab = exit_label;
  316.         genstmt(stmt->s1);
  317.     }
  318.     initstack();
  319.     gen_label(contlab);
  320.     if (stmt->s2 != NULL) {
  321.         size = natural_size( stmt->s2 );
  322.         gen_expr(stmt->s2, F_ALL | F_NOVALUE | F_FREG, size );
  323.     }
  324.     gen_code(op_bra, 0, make_label(loop_label), NULL);
  325.     breaklab = old_break;
  326.     contlab = old_cont;
  327.     gen_label(exit_label);
  328. }
  329.  
  330. void
  331. genif(stmt)
  332.  
  333. /*
  334.  * generate code to evaluate an if statement.
  335.  */
  336.     struct snode   *stmt;
  337. {
  338.     int             lab1, lab2;
  339.     int             determine, cond;
  340.  
  341.     lab1 = nextlabel++; /* else label */
  342.     lab2 = nextlabel++; /* exit label */
  343.  
  344.     determine = cond = FALSE;
  345.  
  346.     if (Options.Optimize) { /* Check for constant conditions */
  347.         opt4(&stmt->exp);
  348.         if (stmt->exp != NULL && (stmt->exp->nodetype == en_icon)) {
  349.             determine = 1;
  350.             cond = (stmt->exp->v.i != 0);
  351.         }
  352.     }
  353.  
  354.     initstack();        /* clear temps */
  355.  
  356.     if (!determine)
  357.         falsejp(stmt->exp, lab1);
  358.  
  359.     if (!determine || cond)
  360.         genstmt(stmt->s1);
  361.  
  362.     if (numlines(stmt->s2) > 0) {   /* else part exists */
  363.         if (!determine) {
  364.             gen_code(op_bra, 0, make_label(lab2), NULL);
  365.             gen_label(lab1);
  366.         }
  367.         if (!determine || !cond)
  368.             genstmt(stmt->s2);
  369.         if (!determine)
  370.             gen_label(lab2);
  371.     }
  372.     else {          /* no else code */
  373.         if (!determine)
  374.             gen_label(lab1);
  375.     }
  376. }
  377.  
  378. void
  379. gendo(stmt)
  380.  
  381. /*
  382.  * generate code for a do - while loop.
  383.  */
  384.     struct snode   *stmt;
  385. {
  386.     int             oldcont, oldbreak;
  387.     int             determine, cond;
  388.  
  389.     oldcont = contlab;
  390.     oldbreak = breaklab;
  391.     contlab = nextlabel++;
  392.     gen_label(contlab);
  393.  
  394.     determine = cond = FALSE;
  395.  
  396.     if (Options.Optimize) {
  397.         opt4(&stmt->exp);
  398.         if (stmt->exp != NULL && stmt->exp->nodetype == en_icon) {
  399.             determine = 1;
  400.             cond = (stmt->exp->v.i != 0);
  401.         }
  402.     }
  403.  
  404.     if (numlines(stmt->s1) > 1) {
  405.         breaklab = nextlabel++;
  406.         genstmt(stmt->s1);  /* generate body */
  407.         initstack();
  408.         if (!determine)
  409.             truejp(stmt->exp, contlab);
  410.         else if (cond)
  411.             gen_code(op_bra, 0, make_label(contlab), NULL);
  412.         gen_label(breaklab);
  413.     }
  414.     else {
  415.         genstmt(stmt->s1);
  416.         initstack();
  417.         if (!determine)
  418.             truejp(stmt->exp, contlab);
  419.         else if (cond)
  420.             gen_code(op_bra, 0, make_label(contlab), NULL);
  421.     }
  422.     breaklab = oldbreak;
  423.     contlab = oldcont;
  424. }
  425.  
  426. void
  427. call_library(lib_name)
  428.  
  429. /*
  430.  * generate a call to a library routine.
  431.  */
  432.     char           *lib_name;
  433. {
  434.     SYM            *sp;
  435.  
  436.     sp = gsearch(lib_name);
  437.     if (sp == NULL) {
  438.         ++global_flag;
  439.         sp = (SYM *) xalloc(sizeof(SYM));
  440.         sp->tp = &stdfunc;
  441.         sp->name = lib_name;
  442.         sp->storage_class = sc_external;
  443.         sp->storage_type = sc_library;
  444.         sp->value.i = 1;        /* Make it referenced   */
  445.         insert(sp, &gsyms);
  446.         --global_flag;
  447.     }
  448.     gen_code(op_jsr, 0, make_intrlab(lib_name), NULL);
  449. }
  450.  
  451. void
  452. genswitch(stmt)
  453.  
  454. /*
  455.  * generate a linear search switch statement.
  456.  */
  457.     struct snode   *stmt;
  458. {
  459.     int             curlab;
  460.     struct snode   *defcase;
  461.     struct amode   *ap;
  462.  
  463.     curlab = nextlabel++;
  464.     defcase = NULL;
  465.     initstack();
  466.     ap = gen_expr(stmt->exp, F_DREG | F_VOL, 4);
  467.     if ((int) ap->preg != NULL)
  468.         gen_code(op_move, 4, ap, makedreg(am_dreg));
  469.     stmt = stmt->s1;
  470.  
  471.     call_library(".cswitch");
  472.  
  473.     while (numlines(stmt) > 0) {
  474.         if (stmt->s2 != NULL) { /* default case ? */
  475.             stmt->label = (long *) curlab;
  476.             defcase = stmt;
  477.         }
  478.         else {
  479.             gen_code(op_dc, 4, make_label(curlab),
  480.                  make_direct(stmt->label));
  481.             stmt->label = (long *) curlab;
  482.         }
  483.         if (numlines(stmt->s1) > 0 && numlines(stmt->next) > 0)
  484.             curlab = nextlabel++;
  485.         stmt = stmt->next;
  486.     }
  487.  
  488.     if (defcase == NULL)
  489.         gen_code(op_dc, 4, make_direct(NULL), make_label(breaklab));
  490.     else
  491.         gen_code(op_dc, 4, make_direct(NULL), make_label((int) (defcase->label)));
  492. }
  493.  
  494. int
  495. bswitch(list)
  496.  
  497. /*
  498.  * bswitch implements a bubble sort on the statement list.
  499.  */
  500.     struct snode  **list;
  501. {
  502.     int             rc;
  503.     struct snode   *sp1, *sp2;
  504.  
  505.     if (list == NULL)
  506.         return 0;
  507.     sp1 = *list;
  508.     if (sp1 == NULL || sp1->next == NULL)
  509.         return 0;
  510.     rc = bswitch(&(sp1->next));
  511.     sp2 = sp1->next;
  512.     if (sp1->value > sp2->value || sp2->s2 != NULL) {
  513.         sp1->next = sp2->next;
  514.         sp2->next = sp1;
  515.         *list = sp2;
  516.         return 1;
  517.     }
  518.     return rc;
  519. }
  520.  
  521. void
  522. gendirswitch(stmt, minval, maxval)
  523.  
  524. /*
  525.  * generate a direct table lookup switch statement.
  526.  */
  527.     struct snode   *stmt;
  528.     int             minval, maxval;
  529. {
  530.     int             curlab, num, tablab;
  531.     struct snode   *defcase, *st2, *st3;
  532.     struct amode   *ap, *ap1, *ap2, *ap3;
  533.  
  534.     defcase = NULL;
  535.     tablab = nextlabel++;
  536.     curlab = nextlabel++;
  537.     initstack();
  538.  
  539.     st3 = NULL;
  540.     for (st2 = stmt->s1; numlines(st2) > 0; st2 = st2->next) {
  541.         if (st2->stype == st_case) {
  542.             st3 = st2;  /* Save the last case    */
  543.             if (st2->s2 != NULL) {  /* Default case                 */
  544.                 st2->label = (long *) curlab;
  545.                 defcase = st2;
  546.             }
  547.             else {
  548.                 st2->value = (int) st2->label;
  549.                 st2->label = (long *) curlab;
  550.             }
  551.             if (numlines(st2->s1) > 0 && numlines(st2->next) > 0)
  552.                 curlab = nextlabel++;
  553.         }
  554.     }
  555.  
  556.     ap = gen_expr(stmt->exp, F_DREG, 4);
  557.  
  558.     if (ap == NULL)
  559.         return;
  560.  
  561.     make_legal(ap, F_DREG, 4);
  562.     ap1 = makedreg(am_dreg);
  563.  
  564.     if ((int) ap->preg != 0)
  565.         gen_code(op_move, 4, ap, ap1);
  566.  
  567.     /*
  568.      * Test for the lower limit
  569.      */
  570.  
  571.     gen_code(op_cmp, 4, ap1, make_immed(minval));
  572.     if (defcase == NULL)
  573.         gen_code(op_blt, 0, make_label(breaklab), NULL);
  574.     else
  575.         gen_code(op_blt, 0, make_label((int) defcase->label), NULL);
  576.  
  577.     /*
  578.      * Test for the upper limit
  579.      */
  580.     if (minval != 0)
  581.         gen_code(op_sub, 4, make_immed(minval), ap1);
  582.     gen_code(op_cmp, 4, ap1, make_immed(maxval - minval));
  583.  
  584.     if (defcase == NULL)
  585.         gen_code(op_bgt, 0, make_label(breaklab), NULL);
  586.     else
  587.         gen_code(op_bgt, 0, make_label((int) defcase->label), NULL);
  588.  
  589.     /*
  590.      * Get the address of the routine to to execute
  591.      */
  592.     gen_code(op_asl, 4, make_immed(2), ap1);
  593.  
  594.     ap2 = makeareg((enum e_am) 0);
  595.     ap3 = makeareg((enum e_am) 1);
  596.     gen_code(op_lea, 0, make_label(tablab), ap2);
  597.  
  598.     ap2->mode = am_indx2;
  599.     ap2->sreg = am_dreg;
  600.     ap2->offset = makenode(en_icon, 0, NULL);
  601.     gen_code(op_move, 4, ap2, ap3);
  602.  
  603.     ap3->mode = am_ind;
  604.     gen_code(op_jmp, 0, ap3, NULL);
  605.  
  606.     /*
  607.      * Make the jump table
  608.      */
  609.  
  610.     gen_label(tablab);
  611.  
  612.     for (num = minval; num <= maxval; num++) {
  613.         st3 = NULL;
  614.         for (st2 = stmt->s1; st2 != NULL; st2 = st2->next) {
  615.             if (st2->stype == st_case && st2->s2 == NULL) {
  616.                 if (st2->value == num) {
  617.                     st3 = st2;
  618.                     break;
  619.                 }
  620.             }
  621.         }
  622.         if (st3 != NULL) {
  623.             gen_code(op_dc, 4, make_label((int) st3->label), NULL);
  624.             st3->s2 = (struct snode *) 2;
  625.         }
  626.         else {
  627.             if (defcase == NULL)
  628.                 gen_code(op_dc, 4, make_label(breaklab), NULL);
  629.             else
  630.                 gen_code(op_dc, 4, make_label((int) defcase->label), NULL);
  631.         }
  632.     }
  633.     gen_code(op_dc, 4, make_direct(0), NULL);
  634. }
  635.  
  636. void
  637. gencase(stmt)
  638.  
  639. /*
  640.  * generate all cases for a switch statement.
  641.  */
  642.     struct snode   *stmt;
  643. {
  644.     while (stmt != NULL) {
  645.         if (stmt->stype == st_comment)
  646.             genstmt(stmt);
  647.         else {
  648.             if (numlines(stmt->s1) > 0) {
  649.                 gen_label((int) (stmt->label));
  650.                 genstmt(stmt->s1);
  651.             }
  652.         }
  653.         stmt = stmt->next;
  654.     }
  655. }
  656.  
  657. void
  658. genxswitch(stmt)
  659.  
  660. /*
  661.  * analyze and generate best switch statement.
  662.  */
  663.     struct snode   *stmt;
  664. {
  665.     int             oldbreak;
  666.     int             minval, maxval, numval, val;
  667.     struct snode   *caselab;
  668.  
  669.     oldbreak = breaklab;
  670.     breaklab = nextlabel++;
  671.  
  672.     numval = 0;
  673.     caselab = stmt->s1;
  674.  
  675.     while (numlines(caselab) > 0) {
  676.         if (caselab->s2 == NULL) {
  677.             val = (int) caselab->label;
  678.             if (numval == 0) {
  679.                 minval = maxval = val;
  680.                 ++numval;
  681.             }
  682.             else {
  683.                 if (val > maxval)
  684.                     maxval = val;
  685.                 if (val < minval)
  686.                     minval = val;
  687.                 ++numval;
  688.             }
  689.         }
  690.         caselab = caselab->next;
  691.     }
  692.  
  693.     if ((maxval - minval) < 4 * numval && (numval > 4))
  694.         gendirswitch(stmt, minval, maxval);
  695.     else
  696.         genswitch(stmt);
  697.  
  698.     gencase(stmt->s1);
  699.     gen_label(breaklab);
  700.     breaklab = oldbreak;
  701. }
  702.  
  703. void
  704. genreturn(stmt)
  705.  
  706. /*
  707.  * generate a return statement.
  708.  */
  709.     struct snode   *stmt;
  710. {
  711.     struct amode   *ap;
  712.     struct enode   *ep;
  713.  
  714.     if (stmt != NULL && stmt->exp != NULL) {
  715.         initstack();
  716.         ep = stmt->exp;
  717.         if (lastfunc->tp->btp->type == bt_double) {
  718.             ap = gen_expr(ep, F_FREG, 8);
  719.             make_legal(ap, F_FREG, 8);
  720.         }
  721.         else {
  722.             ap = gen_expr(ep, F_ALL, 4);
  723.             if (ap->mode == am_immed && ap->offset->nodetype != en_icon)
  724.                 make_legal(ap, F_AREG, 4);
  725.             if (ap->mode != am_dreg || (int) ap->preg != NULL)
  726.                 gen_code(op_move, 4, ap, makedreg(am_dreg));
  727.         }
  728.     }
  729.     if (retlab == -1) {
  730.         retlab = nextlabel++;
  731.         gen_label(retlab);
  732.  
  733.         if (save_mask != 0)
  734.             gen_code(op_movem, 4, pop, make_mask(save_mask));
  735.         gen_code(op_unlk, 0, makeareg((enum e_am) Options.Frame), NULL);
  736.  
  737.         if (Options.Stack) {
  738.             if ( fnamelab == -1 ) {
  739.                 ap = make_label( stringlit( lastfunc->name) );
  740.             }
  741.             else {
  742.                 ap = make_label( fnamelab );
  743.             }
  744.             gen_code(op_lea, 4, ap, makeareg((enum e_am) 0));
  745.             call_library( ".exit" );
  746.         }
  747.  
  748.         gen_code(op_rts, 0, NULL, NULL);
  749.     }
  750.     else
  751.         gen_code(op_bra, 0, make_label(retlab), NULL);
  752. }
  753.  
  754. void
  755. genstmt(stmt)
  756.  
  757. /*
  758.  * genstmt will generate a statement and follow the next pointer until the
  759.  * block is generated.
  760.  */
  761.     struct snode   *stmt;
  762. {
  763.     while (stmt != NULL) {
  764.         initstack();
  765.         switch (stmt->stype) {
  766.         case st_comment:
  767.             if (Options.Annote)
  768.                 gencomment(stmt);
  769.             break;
  770.         case st_stabn:
  771. #ifdef GENERATE_DBX
  772.             if (Options.Debug)
  773.                 genstabn(stmt);
  774. #endif
  775.             break;
  776.         case st_stabs:
  777. #ifdef GENERATE_DBX
  778.             if (Options.Debug)
  779.                 genstabs(stmt);
  780. #endif
  781.             break;
  782.         case st_asm:
  783.             genasm(stmt);
  784.             break;
  785.         case st_label:
  786.             gen_label((int) (stmt->label));
  787.             break;
  788.         case st_goto:
  789.             gen_code(op_bra, 0, make_label((int) (stmt->label)), NULL);
  790.             break;
  791.         case st_expr:
  792.             gen_expr(stmt->exp, F_ALL | F_NOVALUE | F_FREG,
  793.                  natural_size(stmt->exp));
  794.             break;
  795.         case st_return:
  796.             genreturn(stmt);
  797.             break;
  798.         case st_if:
  799.             genif(stmt);
  800.             break;
  801.         case st_while:
  802.             genwhile(stmt);
  803.             break;
  804.         case st_for:
  805.             gen_for(stmt);
  806.             break;
  807.         case st_continue:
  808.             gen_code(op_bra, 0, make_label(contlab), NULL);
  809.             break;
  810.         case st_break:
  811.             gen_code(op_bra, 0, make_label(breaklab), NULL);
  812.             break;
  813.         case st_switch:
  814.             genxswitch(stmt);
  815.             break;
  816.         case st_do:
  817.             gendo(stmt);
  818.             break;
  819.         default:
  820.             fprintf( stderr, "DIAG - unknown statement.\n" );
  821.             break;
  822.         }
  823.         stmt = stmt->next;
  824.     }
  825.     initstack();
  826. }
  827.  
  828. void
  829. genfunc(stmt)
  830.  
  831. /*
  832.  * generate a function body.
  833.  */
  834.     struct snode   *stmt;
  835. {
  836.     int             autolabel, maxlabel;
  837.     struct amode   *ap;
  838.     struct amode   *ap2;
  839.     struct enode   *lnode;
  840.  
  841.     retlab = contlab = breaklab = fnamelab = -1;
  842.  
  843.     autolabel = nextlabel++;
  844.     maxlabel = nextlabel++;
  845.  
  846.     if (lc_auto & 1)    /* if frame size odd */
  847.         ++lc_auto;  /* make it even */
  848.  
  849.     float_auto = 0;     /* No floating point temporaries */
  850.  
  851.     if (Options.Stack) {
  852.         ap = (struct amode *) xalloc(sizeof(struct amode));
  853.         ap->mode = am_immed;
  854.         ap->offset = (struct enode *) xalloc(sizeof(struct enode));
  855.         ap->offset->nodetype = en_labcon;
  856.         ap->offset->v.i = maxlabel;
  857.         
  858.         fnamelab = stringlit( lastfunc->name );
  859.         ap2 = make_label( fnamelab );
  860.  
  861.         gen_code(op_move, 4, ap, makedreg((enum e_am) 0));
  862.         gen_code(op_lea, 4, ap2, makeareg((enum e_am) 0));
  863.         call_library( ".entry" );
  864.     }
  865.  
  866.     lnode = (struct enode *) xalloc(sizeof(struct enode));
  867.     lnode->nodetype = en_labcon;
  868.     lnode->v.i = autolabel;
  869.     ap = (struct amode *) xalloc(sizeof(struct amode));
  870.     ap->mode = am_immed;
  871.     ap->offset = lnode;
  872.  
  873.     gen_code(op_link, 0, makeareg((enum e_am) Options.Frame), ap);
  874.  
  875.     opt1(stmt);
  876.     genstmt(stmt);
  877.  
  878.     initstack();
  879.  
  880.     genreturn(NULL);
  881.  
  882.     nl();
  883.  
  884.     if (Options.Stack) {
  885.         fprintf( output, "L%d\tEQU\t%d\n", maxlabel , maxparmsize+lc_auto );
  886.     }
  887.  
  888.     fprintf( output, "L%d\tEQU\t%d\n", autolabel , -lc_auto );
  889. }
  890.